using GameFramework;
using Unity.VisualScripting;
using UnityEngine;
using UnityGameFramework.Runtime;

namespace LS.UGFUnits
{
    [UnitShortTitle("Data Node")]
    [UnitSurtitle("Set")]
    public sealed class SetDataNode : DataNodeUnit
    {
        [DoNotSerialize]
        [PortLabelHidden]
        public ValueInput Path { get; private set; }
        
        [DoNotSerialize] 
        [PortLabelHidden]
        public ValueInput InputData { get; private set; }
        
        [DoNotSerialize] 
        [PortLabelHidden]
        public ValueOutput OutputData { get; private set; }

        protected override void Definition()
        {
            Path = ValueInput<string>(nameof(Path), string.Empty);
            InputData = ValueInput<object>(nameof(InputData));
            OutputData = ValueOutput<object>(nameof(OutputData));
            Requirement(Path, Input);
            Requirement(InputData, Input);
        }

        protected override ControlOutput In(Flow flow)
        {
            if (Target == null)
            {
                Debug.LogError("GameFramework is not initialized.");
                return Output;
            }

            string path = flow.GetValue<string>(Path);
            object data = flow.GetValue<object>(InputData);
            if (Target.GetNode(path) != null)
            {
                var dataVar = Target.GetData(path);
                if (dataVar.Type != data.GetType())
                {
                    Variable newData = UGFUnits.Utility.GFVariable.CreateVariable(data);
                    Target.SetData(path, newData);
                    ReferencePool.Release(dataVar);
                    dataVar = newData;
                }
                else
                {
                    dataVar.SetValue(data);
                }
            }
            else
            {
                Variable newData = Utility.GFVariable.CreateVariable(data);
                Target.SetData(path, newData);
            }

            flow.SetValue(OutputData, data);
            return base.In(flow);
        }
    }
}